﻿using UnityEngine;
using System.Collections;
using Helper;

namespace Helper{
	public class Movement : MonoBehaviour {
		static Movement AddMovement(GameObject target){
			Movement movement = target.GetComponent<Movement> ();
			if (movement == null) {
				movement = target.AddComponent<Movement> ();
			} else {
				movement.StopAllCoroutines ();
			}
			return movement;
		}
		/// <summary>
		/// 让target物体沿着一条抛物线运动
		/// </summary>
		/// <param name="target">Target.</param>
		/// <param name="startPos">Start position.</param>
		/// <param name="endPos">End position.</param>
		/// <param name="horizontalVelocity">Horizontal velocity.</param>
		/// <param name="gravity">Gravity.</param>
		/// <param name="regionSpeedRate">Region Speed Rate.</param>
		public static Movement MoveAlongParabolic(GameObject target, Vector3 startPos, Vector3 endPos, float horizontalVelocity, float gravity, 
			float regionSpeedRate=1f)
		{
			Movement movement = Movement.AddMovement (target);
			movement.StartCoroutine (movement.MovingAlongParabolic (startPos, endPos, horizontalVelocity, gravity, regionSpeedRate));
			return movement;
		}
		public IEnumerator MovingAlongParabolic(Vector3 startPos, Vector3 endPos, float horizontalVelocity, float gravity, float regionSpeedRate=1f){
			float runTime = 0f;
			Vector3 horizonDir = endPos - startPos;
			horizonDir.y = 0f;
			float totalTime = horizonDir.magnitude / horizontalVelocity;
			while (runTime < totalTime) {
				runTime += Time.deltaTime * regionSpeedRate;
				regionSpeedRate = Mathf.Lerp (regionSpeedRate, 1f, Time.deltaTime * runTime / totalTime);
				transform.position = MyTween.GetPosInParabolic (startPos, endPos, horizontalVelocity, gravity, runTime);
				yield return null;
			}
			transform.position = MyTween.GetPosInParabolic (startPos, endPos, horizontalVelocity, gravity, totalTime);
			Destroy (this);
			yield return null;
		}

		/// <summary>
		/// 让物体沿着路径做平滑的曲线运动
		/// </summary>
		/// <param name="target">Target.</param>
		/// <param name="nodes">Nodes.</param>
		/// <param name="totalTime">Total time.</param>
		public static Movement MoveAlongTweenCurves(GameObject target, Vector3[] nodes, float totalTime){
			Movement movement = Movement.AddMovement (target);
			movement.StartCoroutine (movement.MovingAlongTweenCurves (nodes, totalTime));
			return movement;
		}

		public IEnumerator MovingAlongTweenCurves(Vector3[] nodes, float totalTime){
			float runTime = 0f;
			transform.position = nodes [0];
			while (runTime < totalTime) {
				transform.position = MyTween.GetPos (nodes, runTime / totalTime);
				runTime += Time.deltaTime;
				yield return null;
			}
			yield return null;
		}


		public static Movement MoveAlongLines(GameObject target, Vector3[] nodes, float speed, bool isRotate=false){
			Movement movement = Movement.AddMovement (target);
			movement.StartCoroutine (movement.MovingAlongLines (nodes, speed, isRotate));
			return movement;
		}

		public IEnumerator MovingAlongLines(Vector3[] nodes, float speed, bool isRotate=false){
			int nodeIndex = 0;
			float offsetZero = speed * Time.deltaTime * 1.5f;
			while (nodeIndex < nodes.Length) {
				if (!isRotate) {
					while (Vector3.Distance (transform.position, nodes [nodeIndex]) > offsetZero) {
						transform.position += (nodes [nodeIndex] - transform.position).normalized * speed * Time.deltaTime;
						yield return null;
					}
				} else {
					float curResult;
					float lastResult = 0f;
					float time = 0f;
					float totalTime;
					float totalDis;
					Vector3 moveDir;
					if (nodeIndex > 0) {
						moveDir = nodes [nodeIndex] - nodes [nodeIndex - 1];
						totalDis = moveDir.magnitude;
						totalTime = totalDis / speed;
					} else {
						moveDir = nodes [nodeIndex] - transform.position;
						totalDis = moveDir.magnitude;
						totalTime = totalDis / speed;
					}
					if (totalDis > offsetZero) {
						moveDir.Normalize ();
						while (time < totalTime) {
							curResult = (-Mathf.Cos (time / totalTime * Mathf.PI) + 1f) * totalDis / 2f;
							transform.position += moveDir * (curResult - lastResult);
							lastResult = curResult;
							time += Time.deltaTime;
							yield return null;
						}
					}
					transform.position = nodes [nodeIndex];
					//curResult = lastResult = time = totalTime = totalDis = 0f;
					//totalDis 
				}
				nodeIndex++;
				yield return null;
			}
			yield return null;
		}
	}
}

